﻿#region Imports

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using IEC.ColumnOrdering.SP2007.Application.Domain;
using IEC.ColumnOrdering.SP2007.Application.Services;
using IEC.ColumnOrdering.SP2007.Application.UI.Common;
using IEC.ColumnOrdering.SP2007.Application.UI.Resources.ViewElements;

#endregion

namespace IEC.ColumnOrdering.SP2007.Application.UI.Controls.UserControls
{

    /// <summary>
    /// A view element facilitating column reordering.
    /// </summary>
    public partial class ColumnOrderViewElement : UserControl
    {

        #region Classes

        /// <summary>
        /// Contains string delimiters.
        /// </summary>
        private static class StringDelimiters
        {

            #region Constants

            /// <summary>
            /// Represents the delimiter of items within the hidden fields 
            /// containing field identifiers.
            /// </summary>
            public const string FieldIdHiddenFieldItem = @"#";

            #endregion

        }

        /// <summary>
        /// Contains control identifiers.
        /// </summary>
        private static class ControlId
        {

            #region Constants

            /// <summary>
            /// Represents the control ID of the item literal control, for list fields.
            /// </summary>
            public const string ListFieldItemLiteral = @"itemLiteral";

            /// <summary>
            /// Represents the control ID of the item literal control, for view fields.
            /// </summary>
            public const string ViewFieldItemLiteral = @"itemLiteral";

            #endregion

        }

        /// <summary>
        /// Contains HTML fragments.
        /// </summary>
        private static class HtmlFragments
        {

            #region Constants

            /// <summary>
            /// Represents a string format for the HTML fragment for list items.
            /// </summary>
            public const string ListItemStringFormat = @"<li id=""{0}"" class=""{1}""><span class=""ElementText"">{2}</span></li>";

            #endregion

        }

        /// <summary>
        /// Contains databinding field names.
        /// </summary>
        private static class DataBindingFieldName
        {

            #region Constants

            /// <summary>
            /// Represents the identifier field.
            /// </summary>
            public const string Id = @"Id";

            /// <summary>
            /// Represents the display name field.
            /// </summary>
            public const string DisplayName = @"DisplayName";

            #endregion

        }
       
        #endregion

        #region Fields - Instance Member

        /// <summary>
        /// The column ordering service.
        /// </summary>
        private IColumnOrderingService columnOrderingService = null;

        /// <summary>
        /// The navigation service.
        /// </summary>
        private INavigationService navigationService = null;

        #endregion

        #region Properties - Instance Member

        #region Properties - Instance Member - ColumnOrderViewElement Members

        /// <summary>
        /// Gets the list field column bar container.
        /// </summary>
        /// <value>
        /// The list field column bar container.
        /// </value>
        private Repeater ListFieldColumnBarContainer
        {
            get
            {
                return this.listFieldItemRepeater;
            }
        }

        /// <summary>
        /// Gets the view field column bar container.
        /// </summary>
        /// <value>
        /// The view field column bar container.
        /// </value>
        private Repeater ViewFieldColumnBarContainer
        {
            get
            {
                return this.viewFieldItemRepeater;
            }
        }

        /// <summary>
        /// Gets or sets the list field identifiers.
        /// </summary>
        /// <value>
        /// The list field identifiers.
        /// </value>
        public IList<Guid> ListFieldIdentifiers
        {
            get
            {
                return ColumnOrderViewElement.GetGuids(this.listFieldItemsDataHiddenField);
            }

            set
            {
                ColumnOrderViewElement.SetGuids(this.listFieldItemsDataHiddenField, value);
            }
        }

        /// <summary>
        /// Gets or sets the view field identifiers.
        /// </summary>
        /// <value>
        /// The view field identifiers.
        /// </value>
        public IList<Guid> ViewFieldIdentifiers
        {
            get
            {
                return ColumnOrderViewElement.GetGuids(this.viewFieldItemsDataHiddenField);
            }

            set
            {
                ColumnOrderViewElement.SetGuids(this.viewFieldItemsDataHiddenField, value);
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether hidden fields must be displayed.
        /// </summary>
        /// <value>
        /// <c>true</c> if hidden fields must be displayed; 
        /// otherwise, <c>false</c>.
        /// </value>
        public bool MustDisplayHiddenFields
        {
            get
            {
                return this.mustDisplayHiddenFieldsDataCheckBox.Checked;
            }

            set
            {
                this.mustDisplayHiddenFieldsDataCheckBox.Checked = value;
            }
        }

        /// <summary>
        /// Gets the selected Application identifier.
        /// </summary>
        /// <value>
        /// The selected Application identifier.
        /// </value>
        private Guid SelectedApplicationId
        {
            get
            {
                return ColumnOrderViewElement.GetGuid(this.webApplicationsDataDropDownList);
            }
        }

        /// <summary>
        /// Gets the selected Site identifier.
        /// </summary>
        /// <value>
        /// The selected Site identifier.
        /// </value>
        private Guid SelectedSiteId
        {
            get
            {
                return ColumnOrderViewElement.GetGuid(this.sitesDataDropDownList);
            }
        }

        /// <summary>
        /// Gets the selected Web identifier.
        /// </summary>
        /// <value>
        /// The selected Web identifier.
        /// </value>
        private Guid SelectedWebId
        {
            get
            {
                return ColumnOrderViewElement.GetGuid(this.websDataDropDownList);
            }
        }

        /// <summary>
        /// Gets the selected List identifier.
        /// </summary>
        /// <value>
        /// The selected List identifier.
        /// </value>
        private Guid SelectedListId
        {
            get
            {
                return ColumnOrderViewElement.GetGuid(this.listsDataDropDownList);
            }
        }

        /// <summary>
        /// Gets the selected View identifier.
        /// </summary>
        /// <value>
        /// The selected View identifier.
        /// </value>
        private Guid SelectedViewId
        {
            get
            {
                return ColumnOrderViewElement.GetGuid(this.viewsDataDropDownList);
            }
        }

        #endregion

        #endregion

        #region Methods - Static Member

        /// <summary>
        /// Gets a GUID value from the given <see cref="ListControl"/>.
        /// </summary>
        /// <param name="listControl">
        /// The <see cref="ListControl"/> from which the GUID value is to be extracted.
        /// </param>
        /// <returns>
        /// The <see cref="Guid"/> value selected in <paramref name="listControl"/> if available;
        /// otherwise, <see cref="Guid.Empty"/>.
        /// </returns>
        private static Guid GetGuid(ListControl listControl)
        {
            Guid value = Guid.Empty;

            string selectionValue = listControl.SelectedItem.Value;

            if (!(string.IsNullOrEmpty(selectionValue)))
            {
                value = new Guid(selectionValue);
            }

            return value;
        }

        /// <summary>
        /// Gets the GUIDs in the specified <see cref="HiddenField"/>.
        /// </summary>
        /// <param name="hiddenField">
        /// The hidden field containing the GUID values.
        /// </param>
        /// <returns>
        /// The list of GUIDs contained in <paramref name="hiddenField"/>.
        /// </returns>
        private static IList<Guid> GetGuids(HiddenField hiddenField)
        {
            IList<Guid> guidList = new List<Guid>();

            IList<string> identifiers = hiddenField.Value.Split(
                new string[] { ColumnOrderViewElement.StringDelimiters.FieldIdHiddenFieldItem },
                StringSplitOptions.RemoveEmptyEntries);

            foreach (string identifier in identifiers)
            {
                Guid guid = new Guid(identifier);

                guidList.Add(guid);
            }

            return guidList;
        }

        /// <summary>
        /// Sets the given GUIDs into the specified <see cref="HiddenField"/>.
        /// </summary>
        /// <param name="hiddenField">
        /// The hidden field to contain the GUID values.
        /// </param>
        /// <param name="fields">
        /// The field containing the GUIDs to be stored in <paramref name="hiddenField"/>.
        /// </param>
        private static void SetGuids(HiddenField hiddenField, FieldCollection fields)
        {
            List<string> identifiers = new List<string>();

            foreach (Field field in fields)
            {
                string guidText = field.Id.ToString();

                identifiers.Add(guidText);
            }

            hiddenField.Value = string.Join(
                ColumnOrderViewElement.StringDelimiters.FieldIdHiddenFieldItem,
                identifiers.ToArray());
        }

        /// <summary>
        /// Sets the GUID identifiers in the given fields 
        /// into the specified <see cref="HiddenField"/>.
        /// </summary>
        /// <param name="hiddenField">
        /// The hidden field to contain the GUID values.
        /// </param>
        /// <param name="guidList">
        /// The GUIDs to be stored in <paramref name="hiddenField"/>.
        /// </param>
        private static void SetGuids(HiddenField hiddenField, IList<Guid> guidList)
        {
            List<string> identifiers = new List<string>();

            foreach (Guid guid in guidList)
            {
                string guidText = guid.ToString();

                identifiers.Add(guidText);
            }

            hiddenField.Value = string.Join(
                ColumnOrderViewElement.StringDelimiters.FieldIdHiddenFieldItem, 
                identifiers.ToArray());
        }

        /// <summary>
        /// Loads the content in the specified data source to the given <see cref="ListControl"/>,
        /// using the given data value field and text field to generate the value and text
        /// of each item.
        /// </summary>
        /// <param name="listControl">
        /// The <see cref="ListControl"/> to which the data source will be bound.
        /// </param>
        /// <param name="dataSource">
        /// The data source to be data bound.
        /// </param>
        /// <param name="dataValueField">
        /// The name of the field providing the item value.
        /// </param>
        /// <param name="dataTextField">
        /// The name of the field providing the item text.
        /// </param>
        private static void LoadToDropDownList(
            ListControl listControl,
            object dataSource,
            string dataValueField,
            string dataTextField)
        {
            listControl.Items.Clear();

            listControl.DataValueField = dataValueField;
            listControl.DataTextField = dataTextField;
            listControl.DataSource = dataSource;

            listControl.DataBind();
        }

        /// <summary>
        /// Sets the selected item of the given <see cref="ListControl"/>.
        /// </summary>
        /// <param name="listControl">
        /// The <see cref="ListControl"/> on which the selected item must be set.
        /// </param>
        /// <param name="value">
        /// The value of the selected item.
        /// </param>
        private static void SetSelectedItem(ListControl listControl, string value)
        {
            try
            {
                listControl.SelectedValue = value;
            }
            catch (ArgumentOutOfRangeException)
            {
                // HACK: sink exception; need to address this 
            }
        }

        /// <summary>
        /// Sets up the specified hyperlink using the given addressable information.
        /// </summary>
        /// <param name="hyperlink">
        /// The <see cref="HyperLink"/> to be setup.
        /// </param>
        /// <param name="webAddressable">
        /// The web addressable information to be used in 
        /// setting up <paramref name="webAddressable"/>.
        /// </param>
        private static void SetupAddressableHyperlink(
            HyperLink hyperlink, IWebAddressable webAddressable)
        {
            if (webAddressable != null)
            {
                hyperlink.NavigateUrl = webAddressable.Url.ToString();
                hyperlink.ToolTip = hyperlink.NavigateUrl;

                hyperlink.Visible = true;
            }
            else
            {
                hyperlink.Visible = false;
            }
        }

        /// <summary>
        /// Searches a given collection, for a specified entity.
        /// </summary>
        /// <param name="entity">
        /// The entity to be searched for.
        /// </param>
        /// <param name="collection">
        /// The collection to be searched.
        /// </param>
        /// <returns>
        /// <c>true</c> if <paramref name="entity"/> is in <paramref name="collection"/>;
        /// otherwise, <c>false</c>.
        /// </returns>
        /// <typeparam name="TDomainEntity">
        /// The type of the <see cref="DomainEntity"/> instances contained in <paramref name="collection"/>.
        /// </typeparam>
        private static bool IsInCollection<TDomainEntity>(TDomainEntity entity, DomainEntityCollection<TDomainEntity> collection)
            where TDomainEntity : DomainEntity, new()
        {
            bool isInCollection = false;

            if ((entity != null) && (collection != null))
            {
                foreach (TDomainEntity currentEntity in collection)
                {
                    if (currentEntity.Id == entity.Id)
                    {
                        isInCollection = true;

                        break;
                    }
                }
            }

            return isInCollection;
        }

        #endregion

        #region Methods - Instance Member

        #region Methods - Instance Member - ColumnOrderViewElement Members

        #region Methods - Instance Member - ColumnOrderViewElement Members - (constructors)

        /// <summary>
        /// Initializes a new instance of the <see cref="ColumnOrderViewElement"/> class.
        /// </summary>
        public ColumnOrderViewElement()
        {
            // setup instance state
            this.columnOrderingService = ServiceFactory.GetColumnOrderingService();
            this.navigationService = ServiceFactory.GetNavigationService();
        }

        #endregion
        
        #region Methods - Instance Member - ColumnOrderViewElement Members - (event handlers)

        /// <summary>
        /// Handles the Load event of the Page control.
        /// </summary>
        /// <param name="sender">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// The <see cref="EventArgs"/> instance containing the event data.
        /// </param>
        protected void Page_Load(object sender, EventArgs e)
        {
            if (this.Page.IsPostBack)
            {
                this.HandlePostBackRequest();
            }
            else
            {
                this.HandleInitialRequest();
            }
        }

        /// <summary>
        /// Handles the PreRender event of the Page control.
        /// </summary>
        /// <param name="sender">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// The <see cref="EventArgs"/> instance containing the event data.
        /// </param>
        protected void Page_PreRender(object sender, EventArgs e)
        {
            this.RenderResources();
        }

        /// <summary>
        /// Handles the SelectedIndexChanged event of the webApplicationsDataDropDownList control.
        /// </summary>
        /// <param name="sender">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// The <see cref="EventArgs"/> instance containing the event data.
        /// </param>
        protected void WebApplicationsDataDropDownList_SelectedIndexChanged(
            object sender, EventArgs e)
        {
            this.WebApplicationSelected();
        }

        /// <summary>
        /// Handles the SelectedIndexChanged event of the sitesDataDropDownList control.
        /// </summary>
        /// <param name="sender">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// The <see cref="EventArgs"/> instance containing the event data.
        /// </param>
        protected void SitesDataDropDownList_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.SiteSelected();
        }

        /// <summary>
        /// Handles the SelectedIndexChanged event of the websDataDropDownList control.
        /// </summary>
        /// <param name="sender">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// The <see cref="EventArgs"/> instance containing the event data.
        /// </param>
        protected void WebsDataDropDownList_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.WebSelected();
        }

        /// <summary>
        /// Handles the SelectedIndexChanged event of the listsDataDropDownList control.
        /// </summary>
        /// <param name="sender">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// The <see cref="EventArgs"/> instance containing the event data.
        /// </param>
        protected void ListsDataDropDownList_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.ListSelected();
        }

        /// <summary>
        /// Handles the SelectedIndexChanged event of the viewsDataDropDownList control.
        /// </summary>
        /// <param name="sender">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// The <see cref="EventArgs"/> instance containing the event data.
        /// </param>
        protected void ViewsDataDropDownList_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.ViewSelected();
        }

        /// <summary>
        /// Handles the CheckedChanged event of the mustDisplayHiddenFieldsDataCheckBox control.
        /// </summary>
        /// <param name="sender">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// The <see cref="EventArgs"/> instance containing the event data.
        /// </param>
        protected void MustDisplayHiddenFieldsDataCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            this.AttemptLoadColumnOrdering();
        }

        /// <summary>
        /// Handles the ItemDataBound event of the listFieldItemRepeater control.
        /// </summary>
        /// <param name="sender">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// The <see cref="RepeaterItemEventArgs"/> instance containing the event data.
        /// </param>
        protected void ListFieldItemRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
        {
            this.DataBindListFieldItem(e.Item);
        }

        /// <summary>
        /// Handles the ItemDataBound event of the viewFieldItemRepeater control.
        /// </summary>
        /// <param name="sender">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// The <see cref="RepeaterItemEventArgs"/> instance containing the event data.
        /// </param>
        protected void ViewFieldItemRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
        {
            this.DataBindViewFieldItem(e.Item);
        }

        /// <summary>
        /// Handles the Click event of the saveHeaderActionButton control.
        /// </summary>
        /// <param name="sender">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// The <see cref="EventArgs"/> instance containing the event data.
        /// </param>
        protected void SaveHeaderActionButton_Click(object sender, EventArgs e)
        {
            this.AttemptSaveColumnOrdering();
        }

        /// <summary>
        /// Handles the Click event of the cancelHeaderActionButton control.
        /// </summary>
        /// <param name="sender">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// The <see cref="EventArgs"/> instance containing the event data.
        /// </param>
        protected void CancelHeaderActionButton_Click(object sender, EventArgs e)
        {
            this.Cancel();
        }

        /// <summary>
        /// Handles the Click event of the saveFooterActionButton control.
        /// </summary>
        /// <param name="sender">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// The <see cref="EventArgs"/> instance containing the event data.
        /// </param>
        protected void SaveFooterActionButton_Click(object sender, EventArgs e)
        {
            this.AttemptSaveColumnOrdering();
        }

        /// <summary>
        /// Handles the Click event of the cancelFooterActionButton control.
        /// </summary>
        /// <param name="sender">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// The <see cref="EventArgs"/> instance containing the event data.
        /// </param>
        protected void CancelFooterActionButton_Click(object sender, EventArgs e)
        {
            this.Cancel();
        }

        #endregion

        #region Methods - Instance Member - ColumnOrderViewElement Members - (helpers)

        #region Methods - Instance Member - ColumnOrderViewElement Members - (helpers) - (events)

        /// <summary>
        /// Handles an initial request.
        /// </summary>
        private void HandleInitialRequest()
        {
            this.GenerateViewFromResource(true);

            this.LoadWebApplications();
            this.LoadSites();
            this.LoadWebs();
            this.LoadLists();
            this.LoadViews();

            if (ConfigurationData.EnableCurrentSiteAccessOnly)
            {
                this.PreventSelectionOfSharePointLocation();
            }

            this.AttemptLoadColumnOrdering();
        }

        /// <summary>
        /// Handles an ASP.NET POST-back request.
        /// </summary>
        private void HandlePostBackRequest()
        {
            this.GenerateViewFromResource(false);
        }

        /// <summary>
        /// Renders the resources.
        /// </summary>
        private void RenderResources()
        {
            this.RegisterScripts();
            this.RegisterStyles();
        }

        /// <summary>
        /// Executed when a web application is selected.
        /// </summary>
        private void WebApplicationSelected()
        {
            this.LoadApplicationData();
            this.LoadSites();
            this.LoadSiteData();
            this.LoadWebs();
            this.LoadWebData();
            this.LoadLists();
            this.LoadListData();
            this.LoadViews();
        }

        /// <summary>
        /// Executed when a site is selected.
        /// </summary>
        private void SiteSelected()
        {
            this.LoadSiteData();
            this.LoadWebs();
            this.LoadWebData();
            this.LoadLists();
            this.LoadListData();
            this.LoadViews();
        }

        /// <summary>
        /// Executed when a web is selected.
        /// </summary>
        private void WebSelected()
        {
            this.LoadWebData();
            this.LoadLists();
            this.LoadListData();
            this.LoadViews();
        }

        /// <summary>
        /// Executed when a list is selected.
        /// </summary>
        private void ListSelected()
        {
            this.LoadListData();
            this.LoadViews();
        }

        /// <summary>
        /// Executed when a view is selected.
        /// </summary>
        private void ViewSelected()
        {
            this.LoadViewData();
            this.AttemptLoadColumnOrdering();
        }

        /// <summary>
        /// Attempts to load the column ordering.
        /// </summary>
        private void AttemptLoadColumnOrdering()
        {
            this.Page.Validate();

            if (this.Page.IsValid)
            {
                if (this.IsValidForLoadingViewFields())
                {
                    try
                    {
                        this.LoadColumnOrdering();
                    }
                    catch (Exception ex)
                    {
                        this.navigationService.NavigateToErrorView(ex);
                    }
                }
            }
        }

        /// <summary>
        /// Attempts to save the column ordering.
        /// </summary>
        private void AttemptSaveColumnOrdering()
        {
            this.Page.Validate();

            if (this.Page.IsValid)
            {
                if (this.IsValidForSavingViewFields())
                {
                    try
                    {
                        this.PersistColumnOrdering();
                        this.LoadColumnOrdering();

                        this.Close();
                    }
                    catch (Exception ex)
                    {
                        this.navigationService.NavigateToErrorView(ex);
                    }
                }
            }
        }

        /// <summary>
        /// Closes the view.
        /// </summary>
        private void Close()
        {
            string viewUrl = this.viewsHyperlink.NavigateUrl;

            if (string.IsNullOrEmpty(viewUrl))
            {
                this.Cancel();
            }
            else
            {
                Uri closureUrl = new Uri(viewUrl);

                this.navigationService.NavigateToView(closureUrl);
            }
        }

        /// <summary>
        /// Cancels the view.
        /// </summary>
        private void Cancel()
        {
            this.navigationService.NavigateToRequestingView();
        }

        #endregion

        #region Methods - Instance Member - ColumnOrderViewElement Members - (helpers) - (visual)

        /// <summary>
        /// Prevents the selection of SharePoint locations.
        /// </summary>
        private void PreventSelectionOfSharePointLocation()
        {
            this.SetupSelectionOfSharePointLocation(false);
        }

        /// <summary>
        /// Sets up the selection of SharePoint locations.
        /// </summary>
        /// <param name="canSelect">
        /// <c>true</c> if the SharePoint location can be selected;
        /// otherwise, <c>false</c>.
        /// </param>
        private void SetupSelectionOfSharePointLocation(bool canSelect)
        {
            this.webApplicationsDataDropDownList.Enabled = canSelect;
            this.sitesDataDropDownList.Enabled = canSelect;
            this.websDataDropDownList.Enabled = canSelect;
            this.listsDataDropDownList.Enabled = canSelect;
            this.viewsDataDropDownList.Enabled = canSelect;
        }

        #endregion

        #region Methods - Instance Member - ColumnOrderViewElement Members - (helpers) - (validation)
        
        /// <summary>
        /// Determines whether the control is valid for loading view field data.
        /// </summary>
        /// <returns>
        /// <c>true</c> if the control is valid for loading view field data; 
        /// otherwise, <c>false</c>.
        /// </returns>
        private bool IsValidForLoadingViewFields()
        {
            return this.IsValid();
        }

        /// <summary>
        /// Determines whether the control is valid for saving view field data.
        /// </summary>
        /// <returns>
        /// <c>true</c> if the control is valid for saving view field data; 
        /// otherwise, <c>false</c>.
        /// </returns>
        private bool IsValidForSavingViewFields()
        {
            return this.IsValid();
        }

        /// <summary>
        /// Determines whether the control is valid.
        /// </summary>
        /// <returns>
        /// <c>true</c> if the control is valid; 
        /// otherwise, <c>false</c>.
        /// </returns>
        private bool IsValid()
        {
            bool isValid = false;

            isValid =
                ((this.SelectedApplicationId != Guid.Empty) &&
                (this.SelectedSiteId != Guid.Empty) &&
                (this.SelectedWebId != Guid.Empty) &&
                (this.SelectedListId != Guid.Empty) &&
                (this.SelectedViewId != Guid.Empty));

            return isValid;
        }

        #endregion

        #region Methods - Instance Member - ColumnOrderViewElement Members - (helpers) - (persistence)

        /// <summary>
        /// Loads the web applications.
        /// </summary>
        private void LoadWebApplications()
        {
            ApplicationCollection applications = this.columnOrderingService.GetApplications();

            ColumnOrderViewElement.LoadToDropDownList(
                this.webApplicationsDataDropDownList,
                applications,
                ColumnOrderViewElement.DataBindingFieldName.Id,
                ColumnOrderViewElement.DataBindingFieldName.DisplayName);

            Domain.Application application = this.columnOrderingService.GetApplication();
            bool isInCollection = ColumnOrderViewElement.IsInCollection<Domain.Application>(
                application, applications);

            if ((application != null) && (isInCollection))
            {
                ColumnOrderViewElement.SetSelectedItem(
                    this.webApplicationsDataDropDownList,
                    application.Id.ToString());
            }

            this.LoadApplicationData();
        }

        /// <summary>
        /// Loads the application data.
        /// </summary>
        private void LoadApplicationData()
        {
            if (this.SelectedApplicationId != Guid.Empty)
            {
                Domain.Application application = 
                    this.columnOrderingService.GetApplication(this.SelectedApplicationId);

                ColumnOrderViewElement.SetupAddressableHyperlink(
                    this.webApplicationsHyperlink, application);
            }
        }

        /// <summary>
        /// Loads the sites.
        /// </summary>
        private void LoadSites()
        {
            if (this.SelectedApplicationId != Guid.Empty)
            {
                SiteCollection sites = this.columnOrderingService.GetSites(
                    this.SelectedApplicationId);

                ColumnOrderViewElement.LoadToDropDownList(
                    this.sitesDataDropDownList,
                    sites,
                    ColumnOrderViewElement.DataBindingFieldName.Id,
                    ColumnOrderViewElement.DataBindingFieldName.DisplayName);

                Site site = this.columnOrderingService.GetSite();
                bool isInCollection = ColumnOrderViewElement.IsInCollection<Site>(
                    site, sites);

                if ((site != null) && (isInCollection))
                {
                    ColumnOrderViewElement.SetSelectedItem(
                        this.sitesDataDropDownList,
                        site.Id.ToString());
                }
            }

            this.LoadSiteData();
        }

        /// <summary>
        /// Loads the site data.
        /// </summary>
        private void LoadSiteData()
        {
            if ((this.SelectedApplicationId != Guid.Empty) &&
                (this.SelectedSiteId != Guid.Empty))
            {
                Site site = this.columnOrderingService.GetSite(
                    this.SelectedApplicationId,
                    this.SelectedSiteId);

                ColumnOrderViewElement.SetupAddressableHyperlink(
                    this.sitesHyperlink, site);
            }
        }

        /// <summary>
        /// Loads the webs.
        /// </summary>
        private void LoadWebs()
        {
            if ((this.SelectedApplicationId != Guid.Empty) &&
                (this.SelectedSiteId != Guid.Empty))
            {
                WebCollection webs = this.columnOrderingService.GetWebs(
                    this.SelectedApplicationId,
                    this.SelectedSiteId);

                ColumnOrderViewElement.LoadToDropDownList(
                    this.websDataDropDownList,
                    webs,
                    ColumnOrderViewElement.DataBindingFieldName.Id,
                    ColumnOrderViewElement.DataBindingFieldName.DisplayName);

                Web web = this.columnOrderingService.GetWeb();
                bool isInCollection = ColumnOrderViewElement.IsInCollection<Web>(
                    web, webs);

                if ((webs != null) && (isInCollection))
                {
                    ColumnOrderViewElement.SetSelectedItem(
                        this.websDataDropDownList,
                        web.Id.ToString());
                }
            }

            this.LoadWebData();
        }

        /// <summary>
        /// Loads the web data.
        /// </summary>
        private void LoadWebData()
        {
            if ((this.SelectedApplicationId != Guid.Empty) &&
                (this.SelectedSiteId != Guid.Empty) &&
                (this.SelectedWebId != Guid.Empty))
            {
                Web web = this.columnOrderingService.GetWeb(
                    this.SelectedApplicationId,
                    this.SelectedSiteId,
                    this.SelectedWebId);

                ColumnOrderViewElement.SetupAddressableHyperlink(
                    this.websHyperlink, web);
            }
        }

        /// <summary>
        /// Loads the lists.
        /// </summary>
        private void LoadLists()
        {
            if ((this.SelectedApplicationId != Guid.Empty) &&
                (this.SelectedSiteId != Guid.Empty) &&
                (this.SelectedWebId != Guid.Empty))
            {
                ListCollection lists = this.columnOrderingService.GetLists(
                    this.SelectedApplicationId,
                    this.SelectedSiteId,
                    this.SelectedWebId);

                ColumnOrderViewElement.LoadToDropDownList(
                    this.listsDataDropDownList,
                    lists,
                    ColumnOrderViewElement.DataBindingFieldName.Id,
                    ColumnOrderViewElement.DataBindingFieldName.DisplayName);

                if (ConfigurationData.EnableCurrentSiteAccessOnly)
                {
                    List list = this.columnOrderingService.GetList(
                        this.SelectedApplicationId,
                        this.SelectedSiteId,
                        this.SelectedWebId);

                    if (list != null)
                    {
                        bool isInCollection = ColumnOrderViewElement.IsInCollection<List>(
                            list, lists);

                        if ((lists != null) && (isInCollection))
                        {
                            ColumnOrderViewElement.SetSelectedItem(
                                this.listsDataDropDownList,
                                list.Id.ToString());
                        }
                    }
                }

                this.LoadListData();
            }
        }

        /// <summary>
        /// Loads the list data.
        /// </summary>
        private void LoadListData()
        {
            if ((this.SelectedApplicationId != Guid.Empty) &&
                (this.SelectedSiteId != Guid.Empty) &&
                (this.SelectedWebId != Guid.Empty) &&
                (this.SelectedListId != Guid.Empty))
            {
                List list = this.columnOrderingService.GetList(
                    this.SelectedApplicationId,
                    this.SelectedSiteId,
                    this.SelectedWebId,
                    this.SelectedListId);

                ColumnOrderViewElement.SetupAddressableHyperlink(
                    this.listsHyperlink, list);
            }
        }

        /// <summary>
        /// Loads the views.
        /// </summary>
        private void LoadViews()
        {
            if ((this.SelectedApplicationId != Guid.Empty) &&
                (this.SelectedSiteId != Guid.Empty) &&
                (this.SelectedWebId != Guid.Empty) &&
                (this.SelectedListId != Guid.Empty))
            {
                Domain.ViewCollection views = this.columnOrderingService.GetViews(
                    this.SelectedApplicationId,
                    this.SelectedSiteId,
                    this.SelectedWebId,
                    this.SelectedListId);

                ColumnOrderViewElement.LoadToDropDownList(
                    this.viewsDataDropDownList,
                    views,
                    ColumnOrderViewElement.DataBindingFieldName.Id,
                    ColumnOrderViewElement.DataBindingFieldName.DisplayName);

                if (ConfigurationData.EnableCurrentSiteAccessOnly)
                {
                    Domain.View view = null;
                    Uri sourceUrl = this.navigationService.GetSourceUrl();

                    foreach (Domain.View currentView in views)
                    {
                        if (currentView.Url == sourceUrl)
                        {
                            view = currentView;
                            break;
                        }
                    }

                    bool isInCollection = ColumnOrderViewElement.IsInCollection<Domain.View>(
                        view, views);

                    if ((views != null) && (isInCollection))
                    {
                        ColumnOrderViewElement.SetSelectedItem(
                            this.viewsDataDropDownList,
                            view.Id.ToString());
                    }
                }

                this.LoadColumnOrdering();
            }

            this.LoadListData();
            this.LoadViewData();
        }

        /// <summary>
        /// Loads the view data.
        /// </summary>
        private void LoadViewData()
        {
            if ((this.SelectedApplicationId != Guid.Empty) &&
                (this.SelectedSiteId != Guid.Empty) &&
                (this.SelectedWebId != Guid.Empty) &&
                (this.SelectedListId != Guid.Empty) &&
                (this.SelectedViewId != Guid.Empty))
            {
                Domain.View view = this.columnOrderingService.GetView(
                    this.SelectedApplicationId,
                    this.SelectedSiteId,
                    this.SelectedWebId,
                    this.SelectedListId,
                    this.SelectedViewId);

                ColumnOrderViewElement.SetupAddressableHyperlink(
                    this.viewsHyperlink, view);
            }
        }

        /// <summary>
        /// Loads the column ordering.
        /// </summary>
        private void LoadColumnOrdering()
        {
            FieldCollection listFields =
                this.columnOrderingService.GetFieldsInListNotIncludedInView(
                this.SelectedApplicationId,
                this.SelectedSiteId,
                this.SelectedWebId,
                this.SelectedListId, 
                this.SelectedViewId);

            FieldCollection viewFields =
                this.columnOrderingService.GetFields(
                this.SelectedApplicationId,
                this.SelectedSiteId,
                this.SelectedWebId,
                this.SelectedListId,
                this.SelectedViewId);

            this.AdjustForHiddenFieldVisibility(listFields);
            this.AdjustForHiddenFieldVisibility(viewFields);

            this.ListFieldColumnBarContainer.DataSource = listFields;
            this.ListFieldColumnBarContainer.DataBind();
            ColumnOrderViewElement.SetGuids(this.listFieldItemsDataHiddenField, listFields);

            this.ViewFieldColumnBarContainer.DataSource = viewFields;
            this.ViewFieldColumnBarContainer.DataBind();
            ColumnOrderViewElement.SetGuids(this.viewFieldItemsDataHiddenField, viewFields);
        }

        /// <summary>
        /// Adjusts for hidden field visibility, 
        /// by removing hidden fields from the given collection.
        /// </summary>
        /// <param name="fields">
        /// The fields to be adjusted.
        /// </param>
        private void AdjustForHiddenFieldVisibility(FieldCollection fields)
        {
            if (!(this.MustDisplayHiddenFields))
            {
                for (int index = 0; index < fields.Count;)
                {
                    Field field = fields[index];

                    if (field.IsHidden)
                    {
                        fields.RemoveAt(index);
                    }
                    else
                    {
                        index++;
                    }
                }
            }
        }

        /// <summary>
        /// Data binds the specified list field item.
        /// </summary>
        /// <param name="repeaterItem">
        /// The repeater item to be data bound.
        /// </param>
        private void DataBindListFieldItem(RepeaterItem repeaterItem)
        {
            this.DataBindFieldItem(
                repeaterItem,
                ColumnOrderViewElement.ControlId.ListFieldItemLiteral);
        }

        /// <summary>
        /// Data binds the specified view field item.
        /// </summary>
        /// <param name="repeaterItem">
        /// The repeater item to be data bound.
        /// </param>
        private void DataBindViewFieldItem(RepeaterItem repeaterItem)
        {
            this.DataBindFieldItem(
                repeaterItem,
                ColumnOrderViewElement.ControlId.ViewFieldItemLiteral);
        }

        /// <summary>
        /// Data binds the specified view field item content, 
        /// to the control with the specified identifier.
        /// </summary>
        /// <param name="repeaterItem">
        /// The repeater item to be data bound.
        /// </param>
        /// <param name="controlId">
        /// The identifier of the control to data bind the content of 
        /// <paramref name="repeaterItem"/>.
        /// </param>
        private void DataBindFieldItem(RepeaterItem repeaterItem, string controlId)
        {
            if ((repeaterItem.ItemType == ListItemType.Item) ||
                (repeaterItem.ItemType == ListItemType.AlternatingItem))
            {
                Literal literal = repeaterItem.FindControl(controlId) as Literal;
                Field field = repeaterItem.DataItem as Field;

                string text = string.Empty;

                if ((literal != null) && (field != null))
                {
                    string cssClass = field.IsHidden ?
                        WellKnownCssStyle.DisabledItem :
                        WellKnownCssStyle.EnabledItem;

                    text = string.Format(
                        CultureInfo.CurrentCulture,
                        ColumnOrderViewElement.HtmlFragments.ListItemStringFormat,
                        field.Id,
                        cssClass,
                        field.AuthoringDisplayName);
                }

                literal.Text = text;
            }
        }
        
        /// <summary>
        /// Persists the column ordering.
        /// </summary>
        private void PersistColumnOrdering()
        {
            FieldCollection selectedFields = this.GetSelectedFields();

            this.columnOrderingService.UpdateViewFieldOrder(
                this.SelectedApplicationId,
                this.SelectedSiteId,
                this.SelectedWebId,
                this.SelectedListId,
                this.SelectedViewId,
                selectedFields);
        }

        /// <summary>
        /// Gets the selected fields.
        /// </summary>
        /// <returns>
        /// The selected fields.
        /// </returns>
        private FieldCollection GetSelectedFields()
        {
            FieldCollection selectedFields = new FieldCollection();

            FieldCollection listFields = this.columnOrderingService.GetFields(
                this.SelectedApplicationId,
                this.SelectedSiteId,
                this.SelectedWebId,
                this.SelectedListId);

            IDictionary<Guid, Field> listFieldIndex = new Dictionary<Guid, Field>();

            foreach (Field listField in listFields)
            {
                listFieldIndex[listField.Id] = listField;
            }

            IList<Guid> selectedFieldGuids = this.ViewFieldIdentifiers;

            foreach (Guid listGuid in selectedFieldGuids)
            {
                if (listFieldIndex.ContainsKey(listGuid))
                {
                    Field field = listFieldIndex[listGuid];

                    selectedFields.Add(field);
                }
            }

            return selectedFields;
        }

        #endregion

        #region Methods - Instance Member - ColumnOrderViewElement Members - (helpers) - (resources)

        /// <summary>
        /// Generates the view from resources.
        /// </summary>
        /// <param name="isInitial">
        /// <c>true</c> if the view is being setup initially; 
        /// otherwise, <c>false</c>.
        /// </param>
        private void GenerateViewFromResource(bool isInitial)
        {
            if (isInitial)
            {
                // setup resources
                this.saveHeaderActionButton.Text = 
                    ColumnOrderViewElementResource.OKActionText;
                this.cancelHeaderActionButton.Text = 
                    ColumnOrderViewElementResource.CancelActionText;

                this.webApplicationsCaptionLabel.Text = 
                    ColumnOrderViewElementResource.WebApplicationCaptionText;
                this.webApplicationsHyperlink.Text = 
                    ColumnOrderViewElementResource.GoToWebApplicationActionText;

                this.sitesCaptionLabel.Text = 
                    ColumnOrderViewElementResource.SitesCaptionText;
                this.sitesHyperlink.Text = 
                    ColumnOrderViewElementResource.GoToSitesActionText;

                this.websCaptionLabel.Text = 
                    ColumnOrderViewElementResource.WebCaptionText;
                this.websHyperlink.Text = 
                    ColumnOrderViewElementResource.GoToWebActionText;

                this.listsCaptionLabel.Text = 
                    ColumnOrderViewElementResource.ListCaptionText;
                this.listsHyperlink.Text = 
                    ColumnOrderViewElementResource.GoToListActionText;

                this.viewsCaptionLabel.Text = 
                    ColumnOrderViewElementResource.ViewCaptionText;
                this.viewsHyperlink.Text = 
                    ColumnOrderViewElementResource.GoToViewActionText;

                this.mustDisplayHiddenFieldsCaptionLabel.Text = 
                    ColumnOrderViewElementResource.DisplayHiddenFieldsOptionText;

                this.saveFooterActionButton.Text = 
                    ColumnOrderViewElementResource.OKActionText;
                this.cancelFooterActionButton.Text = 
                    ColumnOrderViewElementResource.CancelActionText;
            }
        }

        /// <summary>
        /// Registers the scripts.
        /// </summary>
        private void RegisterScripts()
        {
            // importing Jquery
            LiteralControl resourceJquery = new LiteralControl();
            resourceJquery.Text = "<script type=\"text/javascript\" src=\"scripts/jquery.js\"></script>";
            this.Page.Header.Controls.Add(resourceJquery);

            // importing Jquery UI
            LiteralControl resourceJqueryUI = new LiteralControl();
            resourceJqueryUI.Text = "<script type=\"text/javascript\" src=\"scripts/jqueryUI.js\"></script>";
            this.Page.Header.Controls.Add(resourceJqueryUI);

            // importing JS
            LiteralControl js = new LiteralControl();
            js.Text = "<script type=\"text/javascript\" src=\"scripts/_.js\"></script>";
            this.Page.Header.Controls.Add(js);

            // importing Application JS
            LiteralControl resourceAppJS = new LiteralControl();
            resourceAppJS.Text = "<script type=\"text/javascript\" src=\"scripts/ColumnOrdering.js\"></script>";
            this.Page.Header.Controls.Add(resourceAppJS);

            // importing global JS
            LiteralControl globalJS = new LiteralControl();
            globalJS.Text = "<script type=\"text/javascript\" src=\"scripts/_Global.js\"></script>";
            this.Page.Header.Controls.Add(globalJS);
        }

        /// <summary>
        /// Registers the styles.
        /// </summary>
        private void RegisterStyles()
        {
            // importing CSS files
            HtmlLink stylesLink = new HtmlLink();
            stylesLink.Attributes["rel"] = "stylesheet";
            stylesLink.Attributes["type"] = "text/css";
            stylesLink.Href = "iec/styles/ColumnOrdering.css";
            this.Page.Header.Controls.Add(stylesLink);
        }

        #endregion

        #endregion

        #endregion

        #endregion

    }

}